const path = require('path');

// 内置中间件
const koaStatic = require('koa-static'); // 引入静态资源映射中间件
const bodyParser = require('koa-body'); // 引入静态资源映射中间件
const compress = require('koa-compress'); // 引入gzip压缩中间件
const cacheControl = require('koa-cache-control'); // 引入缓存控制中间件
const helmet = require('koa-helmet'); // 引入xss过滤中间件
const ejs = require('koa-ejs'); // 引入ejs模板引擎
const cookie = require('koa-cookie').default; // 引入客户端cookie解析中间件
const proxy = require('./proxy'); // 引入代理中间件

const {
  controller,
  service
} = require('./mounter'); // 装载默认文件夹下的文件
const config = require('./config');
const utils = require('../src/utils');

// 导出middleware加载器
module.exports = (app, middleware = {}, isDefaultMiddleware = true) => {

  // 处理代理，必须放在bodyParse前面
  if (Object.keys(config.proxy || {}).length) {
    console.log('config.proxy', config.proxy);
    proxy(app, config.proxy);
  }

  // 设置上下文
  app.use(setContext(app, {
    controller,
    service,
    config,
    utils
  }));

  if (isDefaultMiddleware) {
    ejs(app, {
      root: path.resolve(`${config.root}/src/view/${config.theme}`),
      layout: 'layout',
      viewExt: 'html',
      writeResp: !config.minifier,

      // _with: false,
      async: true,
      cache: true,
      debug: false
    });

    //cookie解析
    app.use(cookie());

    // 处理post请求
    app.use(bodyParser({
      multipart: true
    }));

    // XSS过滤
    app.use(helmet.xssFilter(Object({
      setOnOldIE: true
    }, config.xssFilter)));

  }

  // 用户自定义加载中间件
  let middlewareKeys = [];
  if (Array.isArray(config.middlewares)) {
    middlewareKeys = config.middlewares;
  } else {
    middlewareKeys = Object.keys(middleware);
  }
  middlewareKeys.forEach(item => {
    if (typeof middleware[item] === 'function') {
      middleware[item](app, config);
    } else {
      throw new Error(`没有找到对应的中间件: ${item}`);
    }
  });

  if (isDefaultMiddleware) {
    // gzip压缩
    app.use(compress(Object({
      threshold: 1024,
      flush: require('zlib').Z_SYNC_FLUSH
    }, config.compress)));


    // 缓存控制
    app.use(cacheControl(Object({
      public: 'public'
    }, config.cacheControl)));

    // 静态资源处理
    installKoaStatic(app, config);

  }

};

function installKoaStatic(app, config) {
  // 静态资源目录
  const ROOT = config.root;
  const STATIC_OPTIONS = config.static || {};
  let rootPath = STATIC_OPTIONS.root || null;
  if (!rootPath) {
    rootPath = `${ROOT}/dist/`;
  }
  app.use(koaStatic(rootPath, Object({}, STATIC_OPTIONS.options)));

}

function setContext(app, options = {}) {
  if (typeof options !== 'object') {
    throw new Error('Invalid defaults');
  }

  Object.keys(options).forEach(key => {
    app[key] = options[key];
  });

  return async (ctx, next) => {
    if (!ctx.context) {
      ctx.context = {};
      Object.keys(options).forEach(key => {
        ctx.context[key] = options[key];
      });
    }
    await next();
  };
}
